<template>
    <!--地图挂载dom-->
    <div id="map">
        <div class="MapTool">
            <el-select v-model="type" placeholder="请选择" @change="markerChange">
                <el-option
                        v-for="item in options"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                </el-option>
            </el-select>
        </div>
    </div>
</template>

<script>
    //引入依赖
    import {Map, View, Feature,Overlay} from 'ol'
    import {Vector as VectorSource, OSM,Cluster} from 'ol/source';
    import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
    import {Point} from 'ol/geom'
    import {Icon, Style, Fill, Stroke, Text} from 'ol/style';
    import {toLonLat,fromLonLat} from 'ol/proj'
    import icon from './image/icon.png'

    export default {
        name: 'PictureMarker',
        data() {
            return {
                options: [{
                    value: 'image',
                    label: '图片标注'
                }, {
                    value: 'text',
                    label: '文字标注'
                }, {
                    value: 'image_text',
                    label: '图文标注'
                }, {
                    value: 'overlay',
                    label: '覆盖标注'
                }, {
                    value: 'cluster',
                    label: '聚合标注'
                }],
                value: '',
                type: "image",
            }
        },
        mounted() {
            //初始化地图
            this.map = new Map({
                target: 'map',//指定挂载dom，注意必须是id
                layers: [
                    new TileLayer({
                        source: new OSM()//加载OpenStreetMap
                    }),
                ],
                //配置视图
                view: new View({
                    center: [113.24981689453125, 23.126468438108688], //视图中心位置
                    projection: "EPSG:4326", //指定投影
                    zoom: 12   //缩放到的级别
                })
            });

            //map点击事件
            this.map.on('click', (evt) => {
                //鼠标单击点坐标
                var point = evt.coordinate;
                //添加一个新的标注（矢量要素）
                console.log(this.type)
                switch (this.type) {
                    case "image":
                        this.addImageVectorLabel(point)
                        break;
                    case "text":
                        this.addTextVectorLabel(point)
                        break;
                    case "image_text":
                        this.addVectorLabel(point)
                        break;
                    case "overlay":
                        this.addOverlayLabel(point)
                        break;
                    case "cluster":
                        this.addClusterVectorLabel()
                        break;
                    default:
                        break;
                }
            });

            /**
             * 为map添加鼠标移动事件监听，当指向标注时改变鼠标光标状态
             */
            this.map.on('pointermove',  (e)=> {
                var pixel = this.map.getEventPixel(e.originalEvent);
                var hit = this.map.hasFeatureAtPixel(pixel);
                this.map.getTargetElement().style.cursor = hit ? 'pointer' : '';
            });

            //矢量标注的数据源
            this.vectorSource = new VectorSource();
            //矢量标注图层
            var vectorLayer = new VectorLayer({
                source: this.vectorSource
            });
            this.map.addLayer(vectorLayer);
        },
        methods: {
            //添加图片标注
            addImageVectorLabel(coordinate) {
                //新建一个点要素 ol.Feature
                var newFeature = new Feature({
                    //几何信息
                    geometry: new Point(coordinate)//点几何对象
                });
                //设置要素的样式
                newFeature.setStyle(this.createImageLabelStyle());
                //将新要素添加到数据源中
                this.vectorSource.addFeature(newFeature);
            },
            addTextVectorLabel(coordinate) {
                //新建一个点要素 Feature
                var newFeature = new Feature({
                    //几何信息
                    geometry: new Point(coordinate),
                    //名称属性
                    name: '文字标注'
                });
                //设置要素的样式
                newFeature.setStyle(this.createTextLabelStyle(newFeature));
                //将新要素添加到数据源中
                this.vectorSource.addFeature(newFeature);
            },
            addVectorLabel(coordinate) {
                //新建一个点要素 ol.Feature
                var newFeature = new Feature({
                    //几何信息
                    geometry: new Point(coordinate),
                    //名称属性
                    name: '图文标注'
                });
                //设置要素的样式
                newFeature.setStyle( this.createLabelStyle(newFeature));
                //将新要素添加到数据源中
                this.vectorSource.addFeature(newFeature);
            },
            addOverlayLabel(coordinate) {
                //新增div元素
                var elementDiv = document.createElement('div');
                elementDiv.className = "marker";
                // 获取id为label的元素
                var overlay = document.createElement('div');
                overlay.title = "覆盖标注";
                overlay.id="label";
                // 为ID为label的div层添加div子节点
                overlay.appendChild(elementDiv);
                //新增a元素
                var elementA = document.createElement("a");
                elementA.className = "address";
                elementA.href = "#";
                //设置文本
                this.setInnerText(elementA, overlay.title);
                // 新建的div元素添加a子节点
                elementDiv.appendChild(elementA);

                //实例化图文标注（图形+文本），添加到地图容器中
                var newMarker = new Overlay({
                    position: coordinate,
                    positioning: 'center-center',
                    element: overlay,
                    stopEvent: false
                });
                //添加覆盖标注
                this.map.addOverlay(newMarker);
                //重构一个a标签的覆盖标注
                var newText = new Overlay({
                    position: coordinate,
                    element: elementA
                });
                this.map.addOverlay(newText);
            },
            /**
             * 动态设置元素文本内容（兼容）
             */
            setInnerText(element, text) {
                if (typeof element.textContent == "string") {
                    element.textContent = text;
                } else {
                    element.innerText = text;
                }
            },
            addClusterVectorLabel(){
                var count = 1000;
                var features = new Array(count);
                var longitude=113.24981689453125;
                var latitude=23.126468438108688;
                //将地理经纬度坐标转换成平面坐标
                let numbers = fromLonLat([longitude,latitude]);
                //模拟生成1000个标注
                for (var i = 0; i < count; ++i) {
                    //根据已知的平面坐标，随机生成平面坐标
                    var coordinates = [numbers[0]* Math.random(), numbers[1]* Math.random()];
                    //再将平面坐标转成经纬度坐标
                    let lonLat = toLonLat(coordinates);
                    //创建点要素
                    features[i] = new Feature(new Point(lonLat));
                }
                //添加矢量要素数据源
                this.vectorSource.addFeatures(features);
                //聚合标注数据源
                var clusterSource = new Cluster({
                    distance: 40,
                    source: this.vectorSource
                });
                //加载聚合标注的矢量图层
                var styleCache = {};
                var clusters = new VectorLayer({
                        source: clusterSource,
                        style: function (feature, resolution) {
                            var size = feature.get('features').length;
                            var style = styleCache[size];
                            if (!style) {
                                style = [
                                    new Style({
                                        image: new Icon(//聚合的图标
                                            ({
                                                anchor: [0.0, 0.0],
                                                anchorOrigin: 'top-right',
                                                anchorXUnits: 'fraction',
                                                anchorYUnits: 'pixels',
                                                offsetOrigin: 'top-right',
                                                // offset:[0,10],
                                                //图标缩放比例
                                                scale: 1,
                                                //透明度
                                                opacity: 0.75,
                                                //图标的url
                                                src: icon
                                            })
                                        ),
                                        text: new Text({//聚合的文本
                                            text: size.toString(),
                                            fill: new Fill({
                                                color: '#000'
                                            }),
                                            scale:2
                                        })
                                    })
                                ];
                                styleCache[size] = style;
                            }
                            return style;
                        }
                });
                this.map.addLayer(clusters)
            },
            createImageLabelStyle() {
                return new Style({
                    image: new Icon(//返回一个图片标注
                        ({
                            anchor: [0.5, 60],
                            anchorOrigin: 'top-right',
                            anchorXUnits: 'fraction',
                            anchorYUnits: 'pixels',
                            offsetOrigin: 'top-right',
                            // offset:[0,10],
                            //图标缩放比例
                            scale: 2,
                            //透明度
                            opacity: 0.75,
                            //图标的url
                            src: icon
                        })
                    )
                });
            },
            createTextLabelStyle(feature) {
                return new Style({
                    text: new Text({
                        //位置
                        textAlign: 'center',
                        //基准线
                        textBaseline: 'middle',
                        //文字样式
                        font: 'normal 14px 微软雅黑',
                        scale: 2,
                        //文本内容
                        text: feature.get('name'),
                        //文本填充样式（即文字颜色）
                        fill: new Fill({color: '#ff3300'}),
                        stroke: new Stroke({color: '#ffcc33', width: 2})
                    })
                })
            },
            createLabelStyle(feature) {
                return new Style({
                    image: new Icon(//图片标注
                        ({
                            anchor: [0.5, -30],
                            anchorOrigin: 'top-right',
                            anchorXUnits: 'fraction',
                            anchorYUnits: 'pixels',
                            offsetOrigin: 'top-right',
                            // offset:[0,10],
                            //图标缩放比例
                            // scale:0.5,
                            //透明度
                            opacity: 0.75,
                            //图标的url
                            src: icon
                        })),
                    text: new Text({//文本标注
                        //位置
                        textAlign: 'center',
                        //基准线
                        textBaseline: 'middle',
                        //文字样式
                        font: 'normal 14px 微软雅黑',
                        //文本内容
                        text: feature.get('name'),
                        //文本填充样式（即文字颜色）
                        fill: new Fill({ color: '#ff3300' }),
                        stroke: new Stroke({ color: '#ffcc33', width: 2 })
                    })
                });
            },
            markerChange(type) {
                this.type = type;
            }
        }
    }
</script>

<style>
    #map {
        width: 100%;
        height: 100%;
    }

    .MapTool {
        position: absolute;
        top: .5em;
        right: .5em;
        z-index: 9999;
    }
    .marker {
         width: 50px;
         height: 50px;
         border: 1px solid #163488;
         border-radius: 25px;
         background-color: #ff2f4d;
     }

    .address {
        text-decoration: none;
        color: #ffffff;
        font-size: 20px;
        font-weight: bold;
        text-shadow: black 0.1em 0.1em 0.2em;
    }
</style>
